<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>this is javascript demo</title>
<script type="text/javascript">
	/*方法的构造器调用模式，Quo这个对象的值就是构造方法，怎么确认的呢？因为Quo的首字母是大写的
	  这是一个默认的约定。值是构造器的对象可以直接new的，相当于可以用对象来制造对象。就是这个
	  对象特殊点，是构造器对象。由构造器对象new出来的对象会继承构造器对象本身的prototype中的属
	  性和方法。*/
	var Quo=function(string) {
		this.status=string
	};

	/*构造器对象的prototype中增加一个get_status属性，它的值是一个函数，那么由该构造器对象new出来
	  的对象就继承了这个属性。*/
	Quo.prototype.get_status=function() {
		return this.status;
	};

	var myQuo=new Quo("confused");//在构造函数内部的this就是new出来的对象。
	document.writeln(typeof myQuo);//object,从构造器对象new出来的对象是object类型

	document.writeln(myQuo.get_status());

	var add = function(a,b) {
		if (typeof a !== 'number' || typeof b !== 'number') {
			throw {
				name: 'TypeError',
				message: 'A number args needed'
			};
		}
		return a+b;
	};

	var array = [3,4];

	/*apply调用模式可以用来调用函数和方法，apply接受两个参数，第一个是调用对象的this，第二个是参数
	  列表。当使用apply的方式调用函数时，第一个参数传null，第二个传参数数组。当使用apply方式调对象
	  的方法时，直接将对象作为第一个参数*/
	var sum = add.apply(null,array);
	document.writeln(sum);

	var statusObject = {
		status:'A-OK'
	};

	var status = Quo.prototype.get_status.apply(statusObject);

	document.writeln(status);

	var sum = function() {
		var i,sum=0;
		for (var i = 0; i < arguments.length; i++) {
			sum+=arguments[i]
		}
		return sum;
	};
	document.writeln(sum(1,2,3,4,5));

	var try_it = function() {
		try {
			add(2,'jj');
		}catch(e){
			document.writeln(e.name+":"+e.message);
		}
	};

	try_it();

	/*给Function对象的prototype属性增加一个属性method，它的值是一个函数。那么所有的function类型的对象
	  就都有了这个属性。这里一定要理解为什么Number可以直接访问method这个属性，因为Number和String等都
	  是function类型。*/
	Function.prototype.method=function(name,func) {
		this.prototype[name]=func;
	};


	Number.method('integer',function() {
		return (this>0)?Math.floor(this):Math.ceil(this);
	});

	document.writeln((-10/3).integer());

	String.method('trim',function() {
		return this.replace(/^\s+|\s+$/g,'');
	});

	document.writeln('"'+"     chen        ".trim()+'"');

	var myObject = function() {
		var value=0;
		return {
			increment: function(inc) {
				value += typeof inc === 'number' ? inc:1;
			},
			getValue: function() {
				return value;
			}
		}
	}();

	myObject.increment();//myObject虽然是返回的对象，但是这个对象中的方法还能享有访问value的特权
	myObject.increment();

	document.writeln(myObject.getValue());

	var quo = function(status) {
		return {
			get_status: function() {
				return status;
			}
		};
	};

	//虽然这里已经返回了一个包含有get_status属性的对象，但是这个对象还是具有访问status变量的特权。
	//这种能够访问函数被创建时的上下文环境的能力，被称为闭包。这和前面总结的函数几个隐藏属性刚好
	//印证。包括：上下文、实现函数行为的代码、prototype、“调用”属性
	var myquo = quo("amazed");  
	document.writeln(myquo.get_status());

	var fade = function(node) {
		var level = 1;
		var step = function() {
			var hex = level.toString(16);
			node.style.backgroundColor = '#FFFF'+hex+hex;
			if (level<15) {
				level += 1;
				setTimeout(step, 100);
			}
		};
		setTimeout(step,100);
	};

	fade(document.body);



	document.writeln(":::"+typeof Number+":::");//这些对象的类型竟然都是function
	document.writeln(Number.prototype.constructor);

	document.writeln("---"+typeof String+"---");//function

	document.writeln(typeof Object);//function

	document.writeln(typeof 10/3);


	document.writeln("\n");

	/*给Function的原型中加一个test属性，test属性的值是一个方法，那么所有的函数对象的原型中（prototype）都继承了这个test属性
	  所以下面定义的sub方法的prototype中隐含的继承了这个test属性，因为这个属性的值是函数值，所以sub.test后面加上调用运算符()
	  就可以调用这个函数了。但是我们直接打印这个test属性，结果为undefined，这说明虽然这个属性存在，但是它是继承来的，在sub中
	  不直接可见，下面打印的是sub的prototype属性（该属性是一个对象）的constructor属性，可以看到该属性的值就是sub这个对象的函数值
	  本身。*/
	Function.prototype.test=function(){
		alert("test");
	};

	var sub = function(a,b){
		return a-b;
	}

	sub.test();
	document.writeln("::::"+sub.prototype.test+"::::");
	document.writeln(sub.prototype.constructor);


</script>
</head>

<body>
	<h1>这是一个javascript学习练习</h1>
</body>

</html>